#include "Inc/device.h"
#include "Inc/server.h"

const quint32 freq_table[] = {1522, 1204, 953, 754, 597, 472, 373, 295, 234, 186, 146, 116, 92, 73, 57, 45, 36, 28, 22, 18, 14, 11, 9, 7, 4, 2};

Device::Device(QObject *parent)
    : QObject{parent}
{
}

Device::Device(QObject *parent, quint8 device_id, QTcpSocket *socket, const QString &ip)
    : QObject{parent}, socket_ins(socket), device_id(device_id), ip_addr(ip), device_status(Types::IDLE), last_update(QDateTime::currentDateTime()), cur_voltage(0), cur_freq_index(0)
{
    // 添加默认任务
    Task *voltageTask = new Task(this);
    tasks.append(voltageTask);

    Task *singleTask = new Task(this);
    singleTask->setEnabled(false); // 默认禁用
    singleTask->setTaskType(Types::GET_SINGLE);
    singleTask->setCurrent(Types::AMPL_A5);
    singleTask->setFreq(1000);
    tasks.append(singleTask);

    Task *eisTask = new Task(this);
    eisTask->setEnabled(false); // 默认禁用
    eisTask->setTaskType(Types::GET_EIS);
    eisTask->setCurrent(Types::AMPL_A5);
    tasks.append(eisTask);

    // 启动任务定时器
    connect(&task_timer, &QTimer::timeout, this, &Device::runTask);
    task_timer.start(1000); // 每秒检查一次任务
    
    QByteArray data;
    data.append(static_cast<char>(0x63));   // 新设备
    data.append(static_cast<char>(device_id)); // 设备ID
    data.append(static_cast<char>(Types::IDLE)); // 初始状态
    qobject_cast<Server *>(parent)->sendToPCs(data);
}

Device::~Device()
{
    if (socket_ins)
    {
        socket_ins->disconnectFromHost();
        socket_ins->deleteLater();
    }
    qDeleteAll(results);
    results.clear();
    qDeleteAll(tasks);
    tasks.clear();
    qDebug() << "Device " << device_id << " destroyed.";
}

bool Device::sendToDevice(const QByteArray &data)
{
    if (socket_ins && socket_ins->state() == QAbstractSocket::ConnectedState)
    {
        qint64 bytesWritten = socket_ins->write(data);
        setDeviceStatus(Types::UNKNOWN);
        last_send_time = QDateTime::currentDateTime();
        if (bytesWritten == -1)
        {
            qDebug() << "Error sending data to device:" << socket_ins->errorString();
            return false;
        }
        return true;
    }
    else
    {
        qDebug() << "Socket is not connected.";
        return false;
    }
}

bool Device::newEIS(Types::DrivingCurrent current)
{
    if (getDeviceStatus() != Types::IDLE)
    {
        qDebug() << "Device is busy or task is not empty.";
        return false;
    }
    cur_measure_type = Types::GET_EIS;
    cur_current = current;
    setCurFreqIndex(0);                        // Reset frequency index
    auto result = new Result(Types::GET_EIS, current, this); // Create a new Result object for this measurement
    results.append(result); // Create a new Result object for this measurement
    emit resultsListChanged(results);
    measureAt(cur_current, freq_table[cur_freq_index]);
    QByteArray data;
    data.append(static_cast<char>(0x65));
    data.append(static_cast<char>(device_id));
    data.append(static_cast<char>(Types::GET_EIS)); // 测量任务类型
    data.append(static_cast<char>(current)); // 电流档位
    auto measure_time = result->getCreateTime().toSecsSinceEpoch();
    data.append(reinterpret_cast<const char *>(&measure_time), sizeof(measure_time)); // 测量时间
    qobject_cast<Server *>(parent())->sendToPCs(data);
    return true;
}

bool Device::newSingle(Types::DrivingCurrent current, quint16 freq)
{
    if (getDeviceStatus() != Types::IDLE)
    {
        qDebug() << "Device is busy or task is not empty.";
        return false;
    }
    cur_measure_type = Types::GET_SINGLE;
    cur_current = current;
    setCurFreq(freq); // Set the current frequency
    auto result = new Result(Types::GET_SINGLE, current, this);
    results.append(result);
    emit resultsListChanged(results);
    measureAt(cur_current, freq);
    QByteArray data;
    data.append(static_cast<char>(0x65));
    data.append(static_cast<char>(device_id));
    data.append(static_cast<char>(Types::GET_SINGLE)); // 测量任务类型
    data.append(static_cast<char>(current)); // 电流档位
    auto measure_time = result->getCreateTime().toSecsSinceEpoch();
    data.append(reinterpret_cast<const char *>(&measure_time), sizeof(measure_time)); // 测量时间
    qobject_cast<Server *>(parent())->sendToPCs(data);
    return true;
}

void Device::measureAt(Types::DrivingCurrent vol, quint16 freq)
{
    QByteArray data;
    data.append(static_cast<char>(0x21));        // 命令
    data.append(static_cast<char>(vol));         // 设备ID
    data.append(static_cast<char>(freq >> 8));   // 频率高字节
    data.append(static_cast<char>(freq & 0xFF)); // 频率低字节
    sendToDevice(data);
    qDebug() << "Measure command sent to device " << device_id
             << " with voltage " << static_cast<int>(vol)
             << " and frequency " << freq;
}

void Device::stopMeasure()
{
    QByteArray data;
    cur_measure_type = Types::NONE; // Reset current measurement type
    data.append(static_cast<char>(0x22)); // 停止测量命令
    sendToDevice(data);
    qDebug() << "Stop measure command sent to device " << device_id;
}

void Device::onResultReceived(quint16 volt, double real, double imag)
{
    if (cur_measure_type != Types::GET_EIS && cur_measure_type != Types::GET_SINGLE)
    {
        stopMeasure();
        qDebug() << "Unexpected measurement type received from device " << device_id;
        return;
    }
    setLastUpdate();
    setCurVoltage(volt);
    if (results.size() == 0 || results.last()->size() == sizeof(freq_table) / sizeof(freq_table[0]))
    {
        qDebug() << "Unexpected result received from device " << device_id;
    }
    results.last()->addPoint((float)freq_table[cur_freq_index], getCurVoltage(), imag, real);
    qDebug() << "Result received from device " << device_id
             << ": Voltage = " << getCurVoltage()
             << ", Real = " << real
             << ", Imaginary = " << imag;
    // Check if there are more frequencies to measure
    if (cur_measure_type == Types::GET_SINGLE)
    {
        stopMeasure();
        qDebug() << "Single measurement completed for device " << device_id;
    }
    else if (cur_measure_type == Types::GET_EIS)
    {
        if (cur_freq_index < sizeof(freq_table) / sizeof(freq_table[0]) - 1)
        {
            setCurFreqIndex(cur_freq_index + 1);
            measureAt(cur_current, freq_table[cur_freq_index]);
        }
        else
        {
            stopMeasure();
            qDebug() << "Measurement completed for all frequencies.";
        }
    }
    QByteArray data;
    data.append(static_cast<char>(0x66));
    data.append(static_cast<char>(device_id));
    qobject_cast<Server *>(parent())->sendToPCs(data);
}

void Device::onVoltageReceived(quint16 voltage)
{
    setDeviceStatus(Types::IDLE);
    setLastUpdate();
    setCurVoltage(voltage);
    QByteArray data;
    data.append(static_cast<char>(0x62));
    data.append(static_cast<char>(device_id));
    // 直接写入（小端格式）
    data.append(static_cast<char>(voltage & 0xFF));       // 电压低字节
    data.append(static_cast<char>((voltage >> 8) & 0xFF)); // 电压高字节

    // 遍历所有连接的PC，将电压数据发送给它们
    qobject_cast<Server *>(parent())->sendToPCs(data);
    qDebug() << "Voltage received from device " << device_id << ": " << voltage;
}

void Device::onMeasureAck()
{
    setDeviceStatus(Types::MEASURING);
    setLastUpdate();
    qDebug() << "Measurement started at device " << device_id;
    QByteArray data;
    // 1b指令+1b设备ID+1b测量任务+1b电流档位+2b频率+1b进度
    data.append(static_cast<char>(0x64));
    data.append(static_cast<char>(device_id));
    data.append(static_cast<char>(cur_measure_type));
    data.append(static_cast<char>(cur_current));
    // 小端储存
    data.append(static_cast<char>(freq_table[cur_freq_index] & 0xFF));       // 频率低字节
    data.append(static_cast<char>((freq_table[cur_freq_index] >> 8) & 0xFF)); // 频率高字节
    data.append(static_cast<char>((float)cur_freq_index/25.0 * 100)); // 进度百分比
    qobject_cast<Server *>(parent())->sendToPCs(data);
    qDebug() << "Measurement ACK sent for device " << device_id;
}

void Device::onStopAck()
{
    setDeviceStatus(Types::IDLE);
    setLastUpdate();
    qDebug() << "Measurement stopped at device " << device_id;
}

void Device::runTask()
{
    switch (device_status)
    {
    case Types::IDLE:
        for (auto &task : tasks) {
            // 检查是否到了任务的开始时间
            if (task->isEnabled() && task->getStartTime() <= QDateTime::currentDateTime())
            {
                // 执行任务
                switch (task->getTaskType())
                {
                case Types::GET_VOLTAGE:
                    cur_measure_type = Types::GET_VOLTAGE;
                    sendToDevice(QByteArray::fromHex("23")); 
                    break;
                case Types::GET_SINGLE:
                    newSingle(task->getCurrent(), task->getFreq());
                    break;
                case Types::GET_EIS:
                    newEIS(task->getCurrent());
                    break;
                default:
                    qDebug() << "Unknown task type for device " << device_id;
                    continue; // 跳过未知任务类型;
                }
                if (task->isRepeat())
                {
                    // 如果是重复任务，重新设置开始时间
                    QDateTime newStartTime = task->getStartTime().addMSecs(task->getInterval());
                    if (newStartTime <= QDateTime::currentDateTime()) {
                        newStartTime = QDateTime::currentDateTime().addMSecs(task->getInterval());
                    }
                    task->setStartTime(newStartTime);
                }
                else
                {
                    task->setEnabled(false); // 如果是单次任务，禁用任务
                }
                break;
            }
        }
        break;
    case Types::UNKNOWN:
        // 如果超过 ACK_TIMEOUT 秒未回复，设置为 TIMEOUT 状态
        if (last_send_time.isValid() && last_send_time.addMSecs(ACK_TIMEOUT) < QDateTime::currentDateTime())
        {
            setDeviceStatus(Types::TIMEOUT);
            qDebug() << "Device " << device_id << " timed out.";
        }
        break;
    case Types::MEASURING:
        // 如果超过 MEASURE_TIMEOUT 秒未收到测量结果，设置为 TIMEOUT 状态
        if (last_send_time.isValid() && last_send_time.addMSecs(MEASURE_TIMEOUT) < QDateTime::currentDateTime())
        {
            setDeviceStatus(Types::TIMEOUT);
            qDebug() << "Device " << device_id << " measurement timed out.";
        }
        break;
    case Types::TIMEOUT:
        // 如果超时超过 TIMEOUT_DISCONNECT 秒，断开连接
        if (last_send_time.isValid() && last_send_time.addMSecs(TIMEOUT_DISCONNECT) < QDateTime::currentDateTime())
        {
            // 断开client
            if (socket_ins)
            {
                socket_ins->disconnectFromHost();
                // 后续资源清理由server槽函数管理
            }
        }
        break;
    // case Types::DISCONNECTED:
    //     break;
    default:
        break;
    }
}

void Device::setDeviceStatus(Types::DeviceStatus status)
{
    device_status = status;
    QByteArray data;
    data.append(static_cast<char>(0x61)); // 0x61 is the command for status update
    data.append(static_cast<char>(device_id));
    data.append(static_cast<char>(status)); // Status byte
    qobject_cast<Server *>(parent())->sendToPCs(data);
    emit statusChanged(status);
}

void Device::setTask(quint64 task_id, Task *task)
{
    // 查找任务并设置
    for (auto &existing_task : tasks)
    {
        if (existing_task->getId() == task_id)
        {
            existing_task->setEnabled(task->isEnabled());
            existing_task->setPriority(task->getPriority());
            existing_task->setRepeat(task->isRepeat());
            existing_task->setTaskType(task->getTaskType());
            existing_task->setCurrent(task->getCurrent());
            existing_task->setFreq(task->getFreq());
            existing_task->setInterval(task->getInterval());
            existing_task->setStartTime(QDateTime::currentDateTime().addMSecs(task->getInterval())); // 设置开始时间为当前时间加上间隔

            // 根据优先级重新排序任务列表，数字大的排在前面
            std::sort(tasks.begin(), tasks.end(), [](Task *a, Task *b) {
                return a->getPriority() > b->getPriority();
            });

            qDebug() << "Task with ID" << task_id << "updated.";
            emit tasksListChanged(tasks);
            return;
        }
    }
    qDebug() << "Task with ID" << task_id << "not found.";
}

